package world.snowcrystal.client;


import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.RequestEntity;
import org.springframework.http.ResponseEntity;
import org.springframework.web.client.RestTemplate;
import world.snowcrystal.commons.model.enums.SnowcrystalHeaders;

import java.net.URI;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Base64;
import java.util.List;
import java.util.Random;

public class SnowCrystalApiClient {

    public static final String NONCE_HEADER = SnowcrystalHeaders.NONCE_HEADER.value();
    public static final String SIGNATURE_HEADER = SnowcrystalHeaders.SIGNATURE_HEADER.value();
    public static final String ACCESS_KEY_HEADER = SnowcrystalHeaders.ACCESS_KEY_HEADER.value();
    public static final String TIMESTAMP_HEADER = SnowcrystalHeaders.TIMESTAMP_HEADER.value();
    public static final String REQUEST_HOST_HEADER = SnowcrystalHeaders.REQUEST_HOST_HEADER.value();
    private static final String SALT = "wqeiprqweioprhwsdjiofhndofhn";

    private static final String GATE_WAY_LOCATION = "localhost:8848";

    private MessageDigest instance;
    private RestTemplate restTemplate;

    public SnowCrystalApiClient(RestTemplate template, String accessKey, String secretKey) {
        this.restTemplate = template;
        this.restTemplate.setInterceptors(List.of(((request, body, execution) -> {
            final HttpHeaders headers = request.getHeaders();
            headers.add(TIMESTAMP_HEADER, String.valueOf(System.currentTimeMillis()));
            headers.add(SIGNATURE_HEADER, encode(accessKey, secretKey));
            headers.add(ACCESS_KEY_HEADER, accessKey);
            headers.add(NONCE_HEADER, String.valueOf(new Random().nextLong()));
            return execution.execute(request, body);
        })));
        try {
            this.instance = MessageDigest.getInstance("SHA-256");
        } catch (NoSuchAlgorithmException ignore) {
        }
    }

    private String encode(String accessKey, String secretKey) {
        StringBuilder builder = new StringBuilder();
        builder.append(accessKey).append(secretKey).append(SALT);
        return new String(Base64.getEncoder().encode(instance.digest(builder.toString().getBytes())));
    }


    public String invoke(String url, Object requestData) {

        URI uri = URI.create(url);
        StringBuilder builder = new StringBuilder();
        builder
                .append(uri.getScheme())
                .append("://")
                .append(GATE_WAY_LOCATION)
                .append(uri.getPath());
        final ResponseEntity<String> responseEntity =
                restTemplate.exchange(RequestEntity.post(builder.toString()).header(REQUEST_HOST_HEADER, uri.getHost() + ":" + uri.getPort())
                        .body(requestData), String.class);
        if (responseEntity.getStatusCode() == HttpStatus.OK) {
            System.out.println(responseEntity.getBody());
            return responseEntity.getBody();
        } else {
            return "Error";
        }
    }

}
